#ifndef __LNTHREAD_H__
#define __LNTHREAD_H__

#include "lnstring.h"

struct ln_thread_t
{
  unsigned long tid;
  const char*   thrd_name;

  /* for Memory alloc */
  void*       heap;

  /* for Error Message */
  int          err_id;
  int          err_line;
  const char*  err_filename;
  const char*  err_funcname;
  char         err_msg[128];
  string_map_p err_cache[64];

  /* for user data */
  void*        user_data[64];
  int          user_data_top;
};

typedef struct ln_thread_t * LN_THREAD_PTR;

LN_THREAD_PTR thrd_current ();

LN_THREAD_PTR thrd_create      ( void (*)(void*) , const char* thrd_name);
int      thrd_get_message (struct thread_msg_t* msg, int timeout);
int      thrd_set_message (LN_THREAD_PTR thrd, int msg, int lparam, int wparam);

void*    thrd_alloc       (LN_THREAD_PTR thrd, int   size);
void     thrd_free        (LN_THREAD_PTR thrd, void* p);
void     thrd_init        (LN_THREAD_PTR thrd, const char* thrdname);

void     thrd_close       (LN_THREAD_PTR thrd);

#define  thrd_verify(thrd)  do { if (!thrd) (thrd) = thrd_current(); } while(0)

/*
   respool
*/
struct respool_t
{
  LN_THREAD_PTR thrd;
  char*  pool;
  char*  buff;
  int    buff_size;
  int    total_size;
};

typedef struct respool_t respool;

#define respool_init(r,b,t)   \
  (r).pool = (void*)0,        \
  (r).thrd = t,               \
  (r).buff = (char*)(b),      \
  (r).buff_size = sizeof (b), \
  (r).total_size = 0

char*   respool_alloc (respool * pool, int size);
void    respool_close (respool * pool);

/*
  Error Message
*/
void    er_set_message (string_map_p msg);
void    er_set (LN_THREAD_PTR thrd, int id, ...);

#define er_errid(thrd)  (thrd)->err_id

/*
  CER  : check error code and return if failed
  CEG  : check error code and goto cleanup if failed
  */
#define CER(id)  do { if (id != 0) return id; } while (0)
#define CEG(id)  do { if (id != 0) goto cleanup; } while (0)

/*
  MEM_CER(p,sz) 
  MEM_CEG(p,sz) 
*/
#define MEM_CER(p,sz)                                        \
  do { if (p == NULL) { er_set (thrd, ER_OUT_OF_MEMORY, sz); \
       return er_errid(thrd); } while (0)

#define MEM_CEG(p,sz)                                        \
  do { if (p == NULL) { er_set (thrd, ER_OUT_OF_MEMORY, sz); \
       goto cleanup; } while (0)


#endif
